home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / AlgoWaveTableObject.c < prev    next >
Text File  |  1994-12-27  |  32KB  |  1,028 lines

  1. /* AlgoWaveTableObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "AlgoWaveTableObject.h"
  31. #include "AlgoWaveTableList.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34. #include "CodeCenter.h"
  35. #include "PcodeStack.h"
  36. #include "PcodeSystem.h"
  37. #include "FixedPoint.h"
  38. #include "MainWindowStuff.h"
  39. #include "Alert.h"
  40. #include "Numbers.h"
  41. #include "AlgoWaveTableWindow.h"
  42. #include "WaveTableStorage.h"
  43. #include "CompilerRoot.h"
  44. #include "FunctionCode.h"
  45. #include "BufferedFileInput.h"
  46. #include "BufferedFileOutput.h"
  47.  
  48.  
  49. struct AlgoWaveTableObjectRec
  50.     {
  51.         MyBoolean                                DataModified;
  52.  
  53.         char*                                        Name;
  54.         char*                                        AlgoWaveTableFormula;
  55.  
  56.         MyBoolean                                NeedsToBeRebuilt;
  57.         WaveTableStorageRec*        WaveTableData; /* NIL if not built */
  58.         NumBitsType                            NumBits;
  59.         long                                        NumFrames;
  60.         long                                        NumTables;
  61.  
  62.         AlgoWaveTableWindowRec*    AlgoWaveTableWindow;
  63.  
  64.         struct CodeCenterRec*        CodeCenter;
  65.         struct MainWindowRec*        MainWindow;
  66.         AlgoWaveTableListRec*        AlgoWaveTableList;
  67.  
  68.         short                                        SavedWindowXLoc;
  69.         short                                        SavedWindowYLoc;
  70.         short                                        SavedWindowWidth;
  71.         short                                        SavedWindowHeight;
  72.     };
  73.  
  74.  
  75. /* allocate and create a new algorithmic wave table */
  76. AlgoWaveTableObjectRec*    NewAlgoWaveTableObject(struct CodeCenterRec* CodeCenter,
  77.                                                 struct MainWindowRec* MainWindow,
  78.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  79.     {
  80.         AlgoWaveTableObjectRec*    AlgoWaveTableObj;
  81.  
  82.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  83.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  84.         if (AlgoWaveTableObj == NIL)
  85.             {
  86.              FailurePoint1:
  87.                 return AlgoWaveTableObj;
  88.             }
  89.         AlgoWaveTableObj->Name = StringToBlockCopy("untitled");
  90.         if (AlgoWaveTableObj->Name == NIL)
  91.             {
  92.              FailurePoint2:
  93.                 ReleasePtr((char*)AlgoWaveTableObj);
  94.                 goto FailurePoint1;
  95.             }
  96.         AlgoWaveTableObj->AlgoWaveTableFormula = StringToBlockCopy(
  97.             "# frames : integer; tables : integer; data : fixedarray\x0a");
  98.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  99.             {
  100.              FailurePoint3:
  101.                 ReleasePtr(AlgoWaveTableObj->Name);
  102.                 goto FailurePoint2;
  103.             }
  104.         AlgoWaveTableObj->DataModified = False;
  105.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  106.         AlgoWaveTableObj->WaveTableData = NIL;
  107.         AlgoWaveTableObj->NumBits = eSample16bit;
  108.         AlgoWaveTableObj->NumFrames = 256;
  109.         AlgoWaveTableObj->NumTables = 256;
  110.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  111.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  112.         AlgoWaveTableObj->MainWindow = MainWindow;
  113.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  114.         AlgoWaveTableObj->SavedWindowXLoc = 0;
  115.         AlgoWaveTableObj->SavedWindowYLoc = 0;
  116.         AlgoWaveTableObj->SavedWindowWidth = 0;
  117.         AlgoWaveTableObj->SavedWindowHeight = 0;
  118.         return AlgoWaveTableObj;
  119.     }
  120.  
  121.  
  122. /* dispose of all data structures associated with wave table */
  123. void                                    DisposeAlgoWaveTableObject(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  124.     {
  125.         CheckPtrExistence(AlgoWaveTableObj);
  126.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  127.             {
  128.                 DisposeAlgoWaveTableWindow(AlgoWaveTableObj->AlgoWaveTableWindow);
  129.                 ERROR(AlgoWaveTableObj->AlgoWaveTableWindow != NIL,PRERR(ForceAbort,
  130.                     "DisposeAlgoWaveTableObject: window thing not NIL after disposing"));
  131.             }
  132.         ReleasePtr(AlgoWaveTableObj->Name);
  133.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  134.         if (AlgoWaveTableObj->WaveTableData != NIL)
  135.             {
  136.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  137.             }
  138.         ReleasePtr((char*)AlgoWaveTableObj);
  139.     }
  140.  
  141.  
  142. /* find out if any changes have been made to it */
  143. MyBoolean                            HasAlgoWaveTableObjectBeenModified(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  144.     {
  145.         CheckPtrExistence(AlgoWaveTableObj);
  146.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  147.             {
  148.                 return AlgoWaveTableObj->DataModified
  149.                     || HasAlgoWaveTableWindowBeenModified(AlgoWaveTableObj->AlgoWaveTableWindow);
  150.             }
  151.          else
  152.             {
  153.                 return AlgoWaveTableObj->DataModified;
  154.             }
  155.     }
  156.  
  157.  
  158. static FunctionParamRec        ArgList[] =
  159.     {
  160.         {"frames",eInteger},
  161.         {"tables",eInteger},
  162.         {"data",eArrayOfFixed}
  163.     };
  164. #define ARGLISTLENGTH (sizeof(ArgList) / sizeof(ArgList[0]))
  165.  
  166.  
  167. /* rebuild the wave table and return True if successful */
  168. MyBoolean                            AlgoWaveTableObjectBuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  169.     {
  170.         char*                                Blob;
  171.         PcodeRec*                        FuncCode;
  172.         CompileErrors                Error;
  173.         long                                LineNumber;
  174.         ParamStackRec*            ParamList;
  175.         EvalErrors                    OtherError;
  176.         OpcodeRec*                    ErrorOpcode;
  177.         long                                OffendingInstruction;
  178.         DataTypes                        ReturnType;
  179.         char*                                Buffer;
  180.         largefixedsigned*        Middle;
  181.         long                                Limit;
  182.         long                                Scan;
  183.         long                                NumberOfTablesInIt;
  184.         long                                TotalFrameCount;
  185.  
  186.  
  187.         CheckPtrExistence(AlgoWaveTableObj);
  188.  
  189.         /* make sure we are unbuilt */
  190.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  191.         ERROR(AlgoWaveTableObj->WaveTableData != NIL,PRERR(ForceAbort,
  192.             "AlgoWaveTableObjectBuild:  unbuilt object but it still exists"));
  193.  
  194.         /* bring the world up to date */
  195.         if (!MainWindowMakeUpToDateFunctions(AlgoWaveTableObj->MainWindow))
  196.             {
  197.                 return False;
  198.             }
  199.  
  200.         /* allocate the new wave table thing */
  201.         AlgoWaveTableObj->WaveTableData = NewWaveTableStorage(
  202.             AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj),
  203.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj));
  204.         if (AlgoWaveTableObj->WaveTableData == NIL)
  205.             {
  206.              FailurePointNegative1:
  207.                 AlertHalt("There is not enough memory available to compile the algorithmic "
  208.                     "wave table generator function.",NIL);
  209.             }
  210.         for (Scan = 0; Scan < AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj); Scan += 1)
  211.             {
  212.                 if (!WaveTableStorageAppendEntry(AlgoWaveTableObj->WaveTableData))
  213.                     {
  214.                      FailurePoint0:
  215.                         DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  216.                         goto FailurePointNegative1;
  217.                     }
  218.             }
  219.  
  220.         /* prepare the text blob to be evaluated */
  221.         Blob = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  222.         if (Blob == NIL)
  223.             {
  224.              FailurePoint1:
  225.                 goto FailurePoint0;
  226.             }
  227.  
  228.         /* perform compilation */
  229.         Error = CompileSpecialFunction(ArgList,ARGLISTLENGTH,&LineNumber,
  230.             &ReturnType,Blob,&FuncCode);
  231.         ReleasePtr(Blob);
  232.         /* show the error message if there is one */
  233.         if (Error != eCompileNoError)
  234.             {
  235.                 if (!AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj))
  236.                     {
  237.                         AlertHalt("A compile error occurred but there is not enough "
  238.                             "memory available to display the error message.",NIL);
  239.                         return False;
  240.                     }
  241.                 AlgoWaveTableWindowHiliteLine(AlgoWaveTableObj->AlgoWaveTableWindow,LineNumber - 1);
  242.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  243.                 return False;
  244.             }
  245.  
  246.         /* try to evaluate the code */
  247.         ParamList = NewParamStack();
  248.         if (ParamList == NIL)
  249.             {
  250.              SecondFailurePoint1:
  251.                 DisposePcode(FuncCode);
  252.                 AlertHalt("There is not enough memory available to evaluate the algorithmic "
  253.                     "wave table generator function.",NIL);
  254.                 return False;
  255.             }
  256.         /* add a space for the return value */
  257.         if (!AddIntegerToStack(ParamList,0))
  258.             {
  259.              SecondFailurePoint2:
  260.                 DisposeParamStack(ParamList);
  261.                 goto SecondFailurePoint1;
  262.             }
  263.         /* add the special parameters (SymbolStack order MUST be the same */
  264.         /* order as that used for the Parameterlist) */
  265.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  266.             {
  267.                 goto SecondFailurePoint2;
  268.             }
  269.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  270.             {
  271.                 goto SecondFailurePoint2;
  272.             }
  273.         Buffer = AllocPtrCanFail(AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)
  274.             * AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)
  275.             * sizeof(largefixedsigned),"degeneratesample");
  276.         if (Buffer == NIL)
  277.             {
  278.                 goto SecondFailurePoint2;
  279.             }
  280.         Limit = PtrSize(Buffer);
  281.         for (Scan = 0; Scan < Limit; Scan += 1)
  282.             {
  283.                 Buffer[Scan] = 0;
  284.             }
  285.         if (!AddArrayToStack(ParamList,Buffer))
  286.             {
  287.                 ReleasePtr(Buffer);
  288.                 goto SecondFailurePoint2;
  289.             }
  290.  
  291.         /* executing the actual code */
  292.         OtherError = EvaluatePcode(ParamList,FuncCode,
  293.             AlgoWaveTableObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,
  294.             AlgoWaveTableObj->MainWindow,
  295.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleLeftCopy,
  296.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleRightCopy,
  297.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleMonoCopy,
  298.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableFrameCount,
  299.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableTableCount,
  300.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetWaveTableArray,
  301.             AlgoWaveTableObj->MainWindow,
  302.             (struct InteractionWindowRec* (*)(void*))&MainWindowGetInteractionWindow);
  303.         DisposePcode(FuncCode);
  304.         if (OtherError != eEvalNoError)
  305.             {
  306.                 char*                    FuncNameString;
  307.                 FuncCodeRec*    ErrorFunction;
  308.                 MyBoolean            SuccessFlag;
  309.  
  310.                 /* present error message */
  311.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  312.                 SuccessFlag = False;
  313.                 ErrorFunction = GetFunctionFromOpcode(AlgoWaveTableObj->CodeCenter,ErrorOpcode);
  314.                 if (ErrorFunction == NIL)
  315.                     {
  316.                         FuncNameString = StringToBlockCopy("<anonymous>");
  317.                     }
  318.                  else
  319.                     {
  320.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  321.                     }
  322.                 if (FuncNameString != NIL)
  323.                     {
  324.                         char*                    Key;
  325.  
  326.                         Key = StringToBlockCopy("_");
  327.                         if (Key != NIL)
  328.                             {
  329.                                 char*                    BaseMessage;
  330.  
  331.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  332.                                 if (BaseMessage != NIL)
  333.                                     {
  334.                                         char*                    FixedMessage1;
  335.  
  336.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  337.                                         if (FixedMessage1 != NIL)
  338.                                             {
  339.                                                 char*                    NumberStr;
  340.  
  341.                                                 NumberStr = IntegerToString(OffendingInstruction);
  342.                                                 if (NumberStr != NIL)
  343.                                                     {
  344.                                                         char*                    FixedMessage2;
  345.  
  346.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  347.                                                         if (FixedMessage2 != NIL)
  348.                                                             {
  349.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  350.                                                                 SuccessFlag = True;
  351.                                                                 ReleasePtr(FixedMessage2);
  352.                                                             }
  353.                                                         ReleasePtr(NumberStr);
  354.                                                     }
  355.                                                 ReleasePtr(FixedMessage1);
  356.                                             }
  357.                                         ReleasePtr(BaseMessage);
  358.                                     }
  359.                                 ReleasePtr(Key);
  360.                             }
  361.                         ReleasePtr(FuncNameString);
  362.                     }
  363.                 if (!SuccessFlag)
  364.                     {
  365.                         AlertHalt("There is not enough memory available to show the "
  366.                             "compile error message.",NIL);
  367.                     }
  368.                 DisposeParamStack(ParamList);
  369.                 return False;
  370.             }
  371.  
  372.         /* add the new data */
  373.         Middle = (largefixedsigned*)GetStackArray(ParamList,3);
  374.         if (Middle == NIL)
  375.             {
  376.                 AlertHalt("NIL array returned from algorithmic wave table function.",NIL);
  377.              RebuildFailurePoint1:
  378.                 DisposeParamStack(ParamList);
  379.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  380.                 AlgoWaveTableObj->WaveTableData = NIL;
  381.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  382.                 return False;
  383.             }
  384.         ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
  385.             PRERR(ForceAbort,"AlgoWaveTableObjectBuild:  array alignment error"));
  386.         NumberOfTablesInIt = AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj);
  387.         TotalFrameCount = AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj);
  388.         if ((PtrSize((char*)Middle) / sizeof(largefixedsigned))
  389.             != NumberOfTablesInIt * TotalFrameCount)
  390.             {
  391.                 AlertHalt("Algorithmic wave table function returned array of wrong size.",NIL);
  392.              RebuildFailurePoint2:
  393.                 goto RebuildFailurePoint1;
  394.             }
  395.         for (Scan = 0; Scan < NumberOfTablesInIt; Scan += 1)
  396.             {
  397.                 long                                Index;
  398.  
  399.                 for (Index = 0; Index < TotalFrameCount; Index += 1)
  400.                     {
  401.                         WaveTableStorageSetFrame(AlgoWaveTableObj->WaveTableData,Scan,Index,
  402.                             Middle[(Scan * TotalFrameCount) + Index]);
  403.                     }
  404.             }
  405.         DisposeParamStack(ParamList);
  406.         AlgoWaveTableObj->NeedsToBeRebuilt = False;
  407.         return True;
  408.     }
  409.  
  410.  
  411. /* remove the wave table data */
  412. void                                    AlgoWaveTableObjectUnbuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  413.     {
  414.         CheckPtrExistence(AlgoWaveTableObj);
  415.         if (AlgoWaveTableObj->WaveTableData != NIL)
  416.             {
  417.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  418.                 AlgoWaveTableObj->WaveTableData = NIL;
  419.             }
  420.     }
  421.  
  422.  
  423. /* rebuild the wave table if it hasn't been built and return success flag */
  424. MyBoolean                            AlgoWaveTableObjectMakeUpToDate(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  425.     {
  426.         CheckPtrExistence(AlgoWaveTableObj);
  427.         if ((AlgoWaveTableObj->WaveTableData == NIL) || (AlgoWaveTableObj->NeedsToBeRebuilt)
  428.             || (AlgoWaveTableObj->AlgoWaveTableWindow != NIL))
  429.             {
  430.                 return AlgoWaveTableObjectBuild(AlgoWaveTableObj);
  431.             }
  432.          else
  433.             {
  434.                 return True;
  435.             }
  436.     }
  437.  
  438.  
  439. /* get a copy of the name of this object */
  440. char*                                    AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  441.     {
  442.         char*                                NameTemp;
  443.  
  444.         CheckPtrExistence(AlgoWaveTableObj);
  445.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  446.             {
  447.                 NameTemp = AlgoWaveTableWindowGetNameCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  448.             }
  449.          else
  450.             {
  451.                 NameTemp = CopyPtr(AlgoWaveTableObj->Name);
  452.             }
  453.         if (NameTemp != NIL)
  454.             {
  455.                 SetTag(NameTemp,"AlgoWaveTableNameCopy");
  456.             }
  457.         return NameTemp;
  458.     }
  459.  
  460.  
  461. /* install a new name on the object.  the object becomes owner of the name, so */
  462. /* the caller should not dispose of it. */
  463. void                                    AlgoWaveTableObjectNewName(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  464.                                                 char* Name)
  465.     {
  466.         CheckPtrExistence(AlgoWaveTableObj);
  467.         CheckPtrExistence(Name);
  468.         ReleasePtr(AlgoWaveTableObj->Name);
  469.         SetTag(Name,"AlgoWaveTableName");
  470.         AlgoWaveTableObj->Name = Name;
  471.         AlgoWaveTableObj->DataModified = True;
  472.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  473.         AlgoWaveTableListAlgoWaveTableNameChanged(AlgoWaveTableObj->AlgoWaveTableList,
  474.             AlgoWaveTableObj);
  475.     }
  476.  
  477.  
  478. /* get a copy of the formula that computes the algorithmic wave table */
  479. char*                                    AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  480.     {
  481.         char*                                TextCopy;
  482.  
  483.         CheckPtrExistence(AlgoWaveTableObj);
  484.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  485.             {
  486.                 TextCopy = AlgoWaveTableWindowGetFormulaCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  487.             }
  488.          else
  489.             {
  490.                 TextCopy = CopyPtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  491.             }
  492.         if (TextCopy != NIL)
  493.             {
  494.                 SetTag(TextCopy,"AlgoWaveTableFormulaCopy");
  495.             }
  496.         return TextCopy;
  497.     }
  498.  
  499.  
  500. /* install a new formula for the algorithmic wave table.  the object becomes the */
  501. /* owner of the memory block so the caller should not dispose of it. */
  502. void                                    AlgoWaveTableObjectNewFormula(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  503.                                                 char* Formula)
  504.     {
  505.         CheckPtrExistence(AlgoWaveTableObj);
  506.         CheckPtrExistence(Formula);
  507.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  508.         SetTag(Formula,"AlgoWaveTableFormula");
  509.         AlgoWaveTableObj->AlgoWaveTableFormula = Formula;
  510.         AlgoWaveTableObj->DataModified = True;
  511.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  512.     }
  513.  
  514.  
  515. /* find out how many bits are in each sample frame */
  516. NumBitsType                        AlgoWaveTableObjectGetNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  517.     {
  518.         CheckPtrExistence(AlgoWaveTableObj);
  519.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  520.             {
  521.                 return AlgoWaveTableWindowGetNumBits(AlgoWaveTableObj->AlgoWaveTableWindow);
  522.             }
  523.          else
  524.             {
  525.                 return AlgoWaveTableObj->NumBits;
  526.             }
  527.     }
  528.  
  529.  
  530. /* install a new number of bits in the object. */
  531. void                                    AlgoWaveTableObjectPutNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  532.                                                 NumBitsType NewNumBits)
  533.     {
  534.         CheckPtrExistence(AlgoWaveTableObj);
  535.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  536.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  537.             PRERR(ForceAbort,"AlgoWaveTableObjectPutNumBits:  bad value"));
  538.         AlgoWaveTableObj->NumBits = NewNumBits;
  539.         AlgoWaveTableObj->DataModified = True;
  540.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  541.     }
  542.  
  543.  
  544. /* find out how many frames there are per table */
  545. long                                    AlgoWaveTableObjectGetNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  546.     {
  547.         CheckPtrExistence(AlgoWaveTableObj);
  548.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  549.             {
  550.                 return AlgoWaveTableWindowGetNumTables(AlgoWaveTableObj->AlgoWaveTableWindow);
  551.             }
  552.          else
  553.             {
  554.                 return AlgoWaveTableObj->NumTables;
  555.             }
  556.     }
  557.  
  558.  
  559. /* set the number of tables in the wave table */
  560. void                                    AlgoWaveTableObjectPutNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  561.                                                 long NumTables)
  562.     {
  563.         CheckPtrExistence(AlgoWaveTableObj);
  564.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  565.         if (NumTables < 0)
  566.             {
  567.                 NumTables = 0;
  568.             }
  569.         AlgoWaveTableObj->NumTables = NumTables;
  570.         AlgoWaveTableObj->DataModified = True;
  571.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  572.     }
  573.  
  574.  
  575. /* get number of frames in each table */
  576. long                                    AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  577.     {
  578.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  579.             {
  580.                 return AlgoWaveTableWindowGetNumFrames(AlgoWaveTableObj->AlgoWaveTableWindow);
  581.             }
  582.          else
  583.             {
  584.                 return AlgoWaveTableObj->NumFrames;
  585.             }
  586.     }
  587.  
  588.  
  589. /* set the number of frames in each table */
  590. void                                    AlgoWaveTableObjectPutNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  591.                                                 long NumFrames)
  592.     {
  593.         CheckPtrExistence(AlgoWaveTableObj);
  594.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  595.         AlgoWaveTableObj->NumFrames = NumFrames;
  596.         AlgoWaveTableObj->DataModified = True;
  597.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  598.     }
  599.  
  600.  
  601. /* get a raw slice of data from the wave table.  if the wave table is modified, */
  602. /* this pointer becomes invalid. */
  603. char*                                    AlgoWaveTableObjectGetRawSlice(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  604.                                                 long AlgoWaveTableIndex)
  605.     {
  606.         CheckPtrExistence(AlgoWaveTableObj);
  607.         ERROR((AlgoWaveTableIndex < 0) || (AlgoWaveTableIndex
  608.             > AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)),PRERR(ForceAbort,
  609.             "AlgoWaveTableObjectGetRawSlice:  table index is out of range"));
  610.         return (char*)WaveTableStorageGetTable(AlgoWaveTableObj->WaveTableData,
  611.             AlgoWaveTableIndex);
  612.     }
  613.  
  614.  
  615. /* make the wave table open it's editor window */
  616. MyBoolean                            AlgoWaveTableObjectOpenWindow(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  617.     {
  618.         CheckPtrExistence(AlgoWaveTableObj);
  619.         if (AlgoWaveTableObj->AlgoWaveTableWindow == NIL)
  620.             {
  621.                 AlgoWaveTableObj->AlgoWaveTableWindow
  622.                     = NewAlgoWaveTableWindow(AlgoWaveTableObj->MainWindow,
  623.                     AlgoWaveTableObj,AlgoWaveTableObj->AlgoWaveTableList,
  624.                     AlgoWaveTableObj->SavedWindowXLoc,AlgoWaveTableObj->SavedWindowYLoc,
  625.                     AlgoWaveTableObj->SavedWindowWidth,AlgoWaveTableObj->SavedWindowHeight);
  626.             }
  627.          else
  628.             {
  629.                 AlgoWaveTableWindowBringToTop(AlgoWaveTableObj->AlgoWaveTableWindow);
  630.             }
  631.         return (AlgoWaveTableObj->AlgoWaveTableWindow != NIL);
  632.     }
  633.  
  634.  
  635. /* notify the object that the editor window is closing.  the object should */
  636. /* not take any action. */
  637. void                                    AlgoWaveTableObjectClosingWindowNotify(
  638.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  639.                                                 short NewX, short NewY, short NewWidth, short NewHeight)
  640.     {
  641.         CheckPtrExistence(AlgoWaveTableObj);
  642.         ERROR(AlgoWaveTableObj->AlgoWaveTableWindow == NIL,PRERR(ForceAbort,
  643.             "AlgoWaveTableObjectClosingWindowNotify:  window not open"));
  644.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  645.         AlgoWaveTableObj->SavedWindowXLoc = NewX;
  646.         AlgoWaveTableObj->SavedWindowYLoc = NewY;
  647.         AlgoWaveTableObj->SavedWindowWidth = NewWidth;
  648.         AlgoWaveTableObj->SavedWindowHeight = NewHeight;
  649.     }
  650.  
  651.  
  652. /* the document's name has changed, so we need to update the window */
  653. void                                    AlgoWaveTableObjectGlobalNameChange(AlgoWaveTableObjectRec*
  654.                                                 AlgoWaveTableObj, char* NewFilename)
  655.     {
  656.         CheckPtrExistence(AlgoWaveTableObj);
  657.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  658.             {
  659.                 AlgoWaveTableWindowGlobalNameChange(AlgoWaveTableObj->AlgoWaveTableWindow,
  660.                     NewFilename);
  661.             }
  662.     }
  663.  
  664.  
  665. /* Algorithmic Wave Table Object Subblock Format: */
  666. /*   1-byte format version number */
  667. /*       should be 1 */
  668. /*   2-byte little endian window X position (signed; origin at top-left corner) */
  669. /*   2-byte little endian window Y position */
  670. /*   2-byte little endian window width */
  671. /*   2-byte little endian window height */
  672. /*   4-byte little endian name length descriptor */
  673. /*   n-byte name string (line feed = 0x0a) */
  674. /*   4-byte little endian formula length descriptor */
  675. /*   n-byte formula string (line feed = 0x0a) */
  676. /*   4-byte little endian number of frames */
  677. /*       should be an integral power of 2 in the interval 2..65536 */
  678. /*   4-byte little endian number of tables */
  679. /*   1-byte number of bits */
  680. /*       should be either 8 or 16 */
  681.  
  682.  
  683. /* read in an object from the file. */
  684. FileLoadingErrors            AlgoWaveTableObjectNewFromFile(AlgoWaveTableObjectRec** ObjectOut,
  685.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  686.                                                 struct MainWindowRec* MainWindow,
  687.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  688.     {
  689.         AlgoWaveTableObjectRec*        AlgoWaveTableObj;
  690.         unsigned char                            UnsignedChar;
  691.         signed long                                SignedLong;
  692.         signed short                            SignedShort;
  693.         FileLoadingErrors                    Error;
  694.  
  695.         CheckPtrExistence(Input);
  696.         CheckPtrExistence(CodeCenter);
  697.         CheckPtrExistence(MainWindow);
  698.         CheckPtrExistence(AlgoWaveTableList);
  699.  
  700.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  701.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  702.         if (AlgoWaveTableObj == NIL)
  703.             {
  704.                 Error = eFileLoadOutOfMemory;
  705.              FailurePoint1:
  706.                 return Error;
  707.             }
  708.  
  709.         /*   1-byte format version number */
  710.         /*       should be 1 */
  711.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  712.             {
  713.                 Error = eFileLoadDiskError;
  714.              FailurePoint2:
  715.                 ReleasePtr((char*)AlgoWaveTableObj);
  716.                 goto FailurePoint1;
  717.             }
  718.         if (UnsignedChar != 1)
  719.             {
  720.                 Error = eFileLoadBadFormat;
  721.              FailurePoint3:
  722.                 goto FailurePoint2;
  723.             }
  724.  
  725.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  726.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  727.             {
  728.                 Error = eFileLoadDiskError;
  729.              FailurePoint4:
  730.                 goto FailurePoint3;
  731.             }
  732.         AlgoWaveTableObj->SavedWindowXLoc = SignedShort;
  733.  
  734.         /*   2-byte little endian window Y position */
  735.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  736.             {
  737.                 Error = eFileLoadDiskError;
  738.              FailurePoint5:
  739.                 goto FailurePoint4;
  740.             }
  741.         AlgoWaveTableObj->SavedWindowYLoc = SignedShort;
  742.  
  743.         /*   2-byte little endian window width */
  744.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  745.             {
  746.                 Error = eFileLoadDiskError;
  747.              FailurePoint6:
  748.                 goto FailurePoint5;
  749.             }
  750.         AlgoWaveTableObj->SavedWindowWidth = SignedShort;
  751.  
  752.         /*   2-byte little endian window height */
  753.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  754.             {
  755.                 Error = eFileLoadDiskError;
  756.              FailurePoint7:
  757.                 goto FailurePoint6;
  758.             }
  759.         AlgoWaveTableObj->SavedWindowHeight = SignedShort;
  760.  
  761.         /*   4-byte little endian name length descriptor */
  762.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  763.             {
  764.                 Error = eFileLoadDiskError;
  765.              FailurePoint8:
  766.                 goto FailurePoint7;
  767.             }
  768.         if (SignedLong < 0)
  769.             {
  770.                 Error = eFileLoadBadFormat;
  771.              FailurePoint9:
  772.                 goto FailurePoint8;
  773.             }
  774.  
  775.         /*   n-byte name string (line feed = 0x0a) */
  776.         AlgoWaveTableObj->Name = AllocPtrCanFail(SignedLong,"AlgoWaveTableObjectRec:  name");
  777.         if (AlgoWaveTableObj->Name == NIL)
  778.             {
  779.                 Error = eFileLoadOutOfMemory;
  780.              FailurePoint10:
  781.                 goto FailurePoint9;
  782.             }
  783.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->Name))
  784.             {
  785.                 Error = eFileLoadDiskError;
  786.              FailurePoint11:
  787.                 ReleasePtr(AlgoWaveTableObj->Name);
  788.                 goto FailurePoint10;
  789.             }
  790.  
  791.         /*   4-byte little endian formula length descriptor */
  792.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  793.             {
  794.                 Error = eFileLoadDiskError;
  795.              FailurePoint12:
  796.                 goto FailurePoint11;
  797.             }
  798.         if (SignedLong < 0)
  799.             {
  800.                 Error = eFileLoadBadFormat;
  801.              FailurePoint13:
  802.                 goto FailurePoint12;
  803.             }
  804.  
  805.         /*   n-byte formula string (line feed = 0x0a) */
  806.         AlgoWaveTableObj->AlgoWaveTableFormula = AllocPtrCanFail(SignedLong,
  807.             "AlgoWaveTableObjectRec:  formula");
  808.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  809.             {
  810.                 Error = eFileLoadOutOfMemory;
  811.              FailurePoint14:
  812.                 goto FailurePoint13;
  813.             }
  814.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->AlgoWaveTableFormula))
  815.             {
  816.                 Error = eFileLoadDiskError;
  817.              FailurePoint15:
  818.                 ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  819.                 goto FailurePoint14;
  820.             }
  821.  
  822.         /*   4-byte little endian number of frames */
  823.         /*       should be an integral power of 2 between 2 and 65536 */
  824.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  825.             {
  826.                 Error = eFileLoadDiskError;
  827.              FailurePoint16:
  828.                 goto FailurePoint15;
  829.             }
  830.         if ((SignedLong != 2) && (SignedLong != 4) && (SignedLong != 8)
  831.             && (SignedLong != 16) && (SignedLong != 32) && (SignedLong != 64)
  832.             && (SignedLong != 128) && (SignedLong != 256) && (SignedLong != 512)
  833.             && (SignedLong != 1024) && (SignedLong != 2048) && (SignedLong != 4096)
  834.             && (SignedLong != 8192) && (SignedLong != 16384) && (SignedLong != 32768)
  835.             && (SignedLong != 65536))
  836.             {
  837.                 Error = eFileLoadBadFormat;
  838.              FailurePoint17:
  839.                 goto FailurePoint16;
  840.             }
  841.         AlgoWaveTableObj->NumFrames = SignedLong;
  842.  
  843.         /*   4-byte little endian number of tables */
  844.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  845.             {
  846.                 Error = eFileLoadDiskError;
  847.              FailurePoint18:
  848.                 goto FailurePoint17;
  849.             }
  850.         if (SignedLong < 0)
  851.             {
  852.                 Error = eFileLoadBadFormat;
  853.              FailurePoint19:
  854.                 goto FailurePoint18;
  855.             }
  856.         AlgoWaveTableObj->NumTables = SignedLong;
  857.  
  858.         /*   1-byte number of bits */
  859.         /*       should be either 8 or 16 */
  860.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  861.             {
  862.                 Error = eFileLoadDiskError;
  863.              FailurePoint20:
  864.                 goto FailurePoint19;
  865.             }
  866.         if (UnsignedChar == 8)
  867.             {
  868.                 AlgoWaveTableObj->NumBits = eSample8bit;
  869.             }
  870.         else if (UnsignedChar == 16)
  871.             {
  872.                 AlgoWaveTableObj->NumBits = eSample16bit;
  873.             }
  874.         else
  875.             {
  876.                 Error = eFileLoadBadFormat;
  877.              FailurePoint21:
  878.                 goto FailurePoint20;
  879.             }
  880.  
  881.         /* fill in the other fields */
  882.         AlgoWaveTableObj->DataModified = False;
  883.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  884.         AlgoWaveTableObj->WaveTableData = NIL;
  885.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  886.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  887.         AlgoWaveTableObj->MainWindow = MainWindow;
  888.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  889.  
  890.         *ObjectOut = AlgoWaveTableObj;
  891.         return eFileLoadNoError;
  892.     }
  893.  
  894.  
  895. /* write the object out to the file. */
  896. FileLoadingErrors            AlgoWaveTableObjectWriteDataOut(
  897.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  898.                                                 struct BufferedOutputRec* Output)
  899.     {
  900.         char*                                StringTemp;
  901.  
  902.         CheckPtrExistence(AlgoWaveTableObj);
  903.         CheckPtrExistence(Output);
  904.  
  905.         /*   1-byte format version number */
  906.         /*       should be 1 */
  907.         if (!WriteBufferedUnsignedChar(Output,1))
  908.             {
  909.                 return eFileLoadDiskError;
  910.             }
  911.  
  912.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  913.         /* note that if the window is open when the file is saved, then the most recent */
  914.         /* coordinates of the window will not be used. */
  915.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowXLoc))
  916.             {
  917.                 return eFileLoadDiskError;
  918.             }
  919.  
  920.         /*   2-byte little endian window Y position */
  921.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowYLoc))
  922.             {
  923.                 return eFileLoadDiskError;
  924.             }
  925.  
  926.         /*   2-byte little endian window width */
  927.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowWidth))
  928.             {
  929.                 return eFileLoadDiskError;
  930.             }
  931.  
  932.         /*   2-byte little endian window height */
  933.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowHeight))
  934.             {
  935.                 return eFileLoadDiskError;
  936.             }
  937.  
  938.         /*   4-byte little endian name length descriptor */
  939.         StringTemp = AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObj);
  940.         if (StringTemp == NIL)
  941.             {
  942.                 return eFileLoadOutOfMemory;
  943.             }
  944.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  945.             {
  946.                 ReleasePtr(StringTemp);
  947.                 return eFileLoadDiskError;
  948.             }
  949.  
  950.         /*   n-byte name string (line feed = 0x0a) */
  951.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  952.             {
  953.                 ReleasePtr(StringTemp);
  954.                 return eFileLoadDiskError;
  955.             }
  956.         ReleasePtr(StringTemp);
  957.  
  958.         /*   4-byte little endian formula length descriptor */
  959.         StringTemp = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  960.         if (StringTemp == NIL)
  961.             {
  962.                 return eFileLoadOutOfMemory;
  963.             }
  964.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  965.             {
  966.                 ReleasePtr(StringTemp);
  967.                 return eFileLoadDiskError;
  968.             }
  969.  
  970.         /*   n-byte formula string (line feed = 0x0a) */
  971.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  972.             {
  973.                 ReleasePtr(StringTemp);
  974.                 return eFileLoadDiskError;
  975.             }
  976.         ReleasePtr(StringTemp);
  977.  
  978.         /*   4-byte little endian number of frames */
  979.         /*       should be an integral power of 2 between 2 and 65536 */
  980.         if (!WriteBufferedSignedLongLittleEndian(Output,
  981.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  982.             {
  983.                 return eFileLoadDiskError;
  984.             }
  985.  
  986.         /*   4-byte little endian number of tables */
  987.         if (!WriteBufferedSignedLongLittleEndian(Output,
  988.             AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  989.             {
  990.                 return eFileLoadDiskError;
  991.             }
  992.  
  993.         /*   1-byte number of bits */
  994.         /*       should be either 8 or 16 */
  995.         switch (AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj))
  996.             {
  997.                 default:
  998.                     EXECUTE(PRERR(ForceAbort,"AlgoWaveTableObjectWriteDataOut:  bad num bits"));
  999.                     break;
  1000.                 case eSample8bit:
  1001.                     if (!WriteBufferedUnsignedChar(Output,8))
  1002.                         {
  1003.                             return eFileLoadDiskError;
  1004.                         }
  1005.                     break;
  1006.                 case eSample16bit:
  1007.                     if (!WriteBufferedUnsignedChar(Output,16))
  1008.                         {
  1009.                             return eFileLoadDiskError;
  1010.                         }
  1011.                     break;
  1012.             }
  1013.  
  1014.         return eFileLoadNoError;
  1015.     }
  1016.  
  1017.  
  1018. /* mark algorithmic wave table object as saved */
  1019. void                                    AlgoWaveTableObjectMarkAsSaved(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  1020.     {
  1021.         CheckPtrExistence(AlgoWaveTableObj);
  1022.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  1023.             {
  1024.                 AlgoWaveTableWindowWritebackModifiedData(AlgoWaveTableObj->AlgoWaveTableWindow);
  1025.             }
  1026.         AlgoWaveTableObj->DataModified = False;
  1027.     }
  1028.